//这里我们按照数据集对一个文件进行读操作
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>

#define MAX_LINE_SIZE 1024

//这里获取最大缓冲区的大小和记录的数量
void get_the_range_of_trance(char* trace_file, long* buf_size,long* record_count){
    //这里获得一个trace文件的范围
    //首先获取trace文件
    //将起始offset和最大offset都创建出来，注意考虑size造成的偏移
    FILE *fp_read = NULL;
    char line[MAX_LINE_SIZE];

    //初始化范围
    *buf_size = -1;
    *record_count = 0;
    
    //循环变量
    long j;
    int i;

    //临时记录当前访问范围的变量
    long buf_size_temp;

    printf("开始运行\n");

    if((fp_read = fopen(trace_file, "r")) != NULL){
        printf("开始读取\n");

        char delims[] = ",";
        char *result = NULL;

        while (fgets(line, MAX_LINE_SIZE, fp_read)){
            //这里是个分割的元素
            result = strtok( line, delims );

            // printf("%s", result);

            //这里要进行计数，只保留第5列
            i = 1;

            //只要还有可以分的，那result不会是NULL
            while((result = strtok( NULL, delims))){
                i++;
                
                //这里将offset也考虑在内
                if(i == 2){
                    buf_size_temp = atol(result);

                    if(*buf_size == -1){
                        *buf_size = buf_size_temp;
                    }else if(*buf_size < buf_size_temp){
                        *buf_size = buf_size_temp;
                    }
                }
            }
            
            (*record_count)++;
        }

        printf("读取完毕\n");
        fclose(fp_read);
        fp_read = NULL;
    }
}

//将访问数据读到内存
void get_access_information(char* trace_file, long* offset_arr, long* size_arr, long record_count){
    //这里获得一个trace文件的范围
    //首先获取trace文件
    //将起始offset和最大offset都创建出来，注意考虑size造成的偏移
    FILE *fp_read = NULL;
    char line[MAX_LINE_SIZE];

    //循环变量
    long j;
    int i;

    //一个用来记录当前存储位置的变量
    long now_index = 0;

    //临时记录当前访问范围的变量
    long begin_temp;
    long size_temp;

    printf("开始运行\n");

    if((fp_read = fopen(trace_file, "r")) != NULL){
        printf("开始读取\n");

        char delims[] = ",";
        char *result = NULL;

        if(now_index > record_count){
            printf("数组爆了\n");
            exit(-1);
        }

        while (fgets(line, MAX_LINE_SIZE, fp_read)){
            //这里是个分割的元素
            result = strtok( line, delims );

            // printf("%s", result);

            //这里要进行计数，只保留第5列
            i = 1;

            if(i == 1){
                begin_temp = atol(result);
                // printf("%ld\n", begin_temp);
                
                offset_arr[now_index] = begin_temp;
            }

            //只要还有可以分的，那result不会是NULL
            while((result = strtok( NULL, delims))){
                i++;
                
                // if(i == 4){
    
                // }

                // if(i == 5){
                //     begin_temp = atol(result);
                //     // printf("%ld\n", begin_temp);
                    
                //     offset_arr[now_index] = begin_temp;
                // }
                
                // //这里将offset也考虑在内
                if(i == 2){
                    size_temp = atol(result);
                    // printf("%ld\n", size_temp);
                    size_arr[now_index] = size_temp;
                }
            }

            now_index++;
        }

        printf("读取完毕\n");
        fclose(fp_read);
        fp_read = NULL;
    }
}

int main(){
    long begin;
    long end;
    long size;
    long record_count;

    //这里看看最大buf size
    long buf_size;

    long* offset_arr;
    long* size_arr;
    FILE *fp_write = NULL;

    //用来写一个文件的空缓冲区
    char write_buf[1048576];
    printf("sizeof(char) = %lu\n",sizeof(char));

    int test_file;
    
    get_the_range_of_trance("./fix-tracecsv", &buf_size, &record_count);

    // if((fp_write = fopen("test", "w+")) == NULL){
    //     printf("文件写开启失败\n");
    //     return -1;
    // }

    // fclose(fp_write);
    
    int fd1;

    fd1=open("test",O_CREAT | O_RDWR,00777);
    if(fd1!=-1){
        printf("file is created.\n");
    }
    
    // int j;
    // printf("end = %ld\n", end);
    // for(j = 0; j < (size+buf_size+begin)/1048576; j++){
    //     printf("写文件，第%d次\n",j);
    //     write(fd1,write_buf,1048576);
    // }

    // write(fd1,write_buf,1048576);

    // truncate ("test1", size+buf_size);// 必须在fopen之后;
    
    // close (fd1);
    

    //这里申请一个堆区空间
    offset_arr = (long *)malloc(sizeof(long)*(record_count + 1));
    size_arr = (long *)malloc(sizeof(long)*(record_count+1));

    //访问的数据拿到内存
    get_access_information("./fix-tracecsv", offset_arr, size_arr, record_count + 1);
    
    
    //这里遍历整个数组，对文件进行访问
    // test_file = open("test", O_RDWR,00777);

    void* buf = (void *)malloc(buf_size + 1);

    memset(buf, 0, buf_size + 1);

    

    //这里记录两种操作的次数
    long read_count = 0;
    
    long rc;

    // rc = read(fd1, buf ,1024);
    // if(rc == -1){
    //     printf("错\n");
	// 	        exit(-1);
    // }
    //这里准备开始计时
    struct timeval start_time, end_time;
    gettimeofday( &start_time, NULL );
    printf("start : %ld.%d\n", start_time.tv_sec, start_time.tv_usec);
    
    printf("准备完毕进行测试\n");
    int i;

    //进行5轮测试
    int all_time = 0;

    for(all_time = 0; all_time < 5; all_time++){
        for(i = 0; i < record_count; i++){
            if(i % 100000 == 0){
                printf("正在测试第%d00000个\n", i / 100000);
            }

            //这里进行读
            //这里进行4K对齐
            if(size_arr[i]*4096 == 0 && offset_arr[i]%4096 == 0){
                rc = pread(fd1, buf, size_arr[i], offset_arr[i]%17179869184);
            }
            
            if(rc == -1){
                printf("r这是错误的i:%d\n", i);
                printf("size_arr[i] = %ld, offset_arr[i] = %ld\n", size_arr[i], offset_arr[i]);
                exit(-1);
            }else{
                // printf("r这是正确的i:%d\n", i);
            }
            read_count++;
        }
    }


    
    
    printf("测试完毕\n");

    gettimeofday( &end_time, NULL );
    printf("end   : %ld.%d\n", end_time.tv_sec, end_time.tv_usec);

    printf("读取的次数:%ld\n", read_count);
    

    free(buf);
    free(offset_arr);
    free(size_arr);
    close(fd1);
    // close(test_file);
    return 0;
}
